package com.bian.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.bian.domain.BianSaccadeTrials;
import com.bian.domain.Body;
import com.bian.mapper.BianSaccadeTrialsMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;


@Slf4j
@Component
@ServerEndpoint("/ws/{userId}")
public class WebSocketServer {
    // 静态变量，用来记录当前在线连接数
    private static int onlineCount = 0;
    // concurrent包的线程安全Set，用来存放每个客户端对应的WebSocketServer对象
    private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<>();
    // 用户ID与Session的映射
    private static ConcurrentHashMap<String, Body> sessionMap = new ConcurrentHashMap<>();
    @Resource
    private BianSaccadeTrialsMapper saccadeTrialsMapper;
    private Session session;
    private String userId;

    @OnOpen
    public void onOpen(Session session, @PathParam("userId") String userId) {
        this.userId = userId;
        webSocketSet.add(this);
        sessionMap.put(userId, new Body().setUserId(userId).setSession(session));
        addOnlineCount();
        log.info("用户" + userId + "加入！当前在线人数为" + getOnlineCount());
    }

    @OnClose
    public void onClose() {
        webSocketSet.remove(this);
        sessionMap.remove(userId);
        subOnlineCount();
        log.info("用户" + userId + "退出！当前在线人数为" + getOnlineCount());
    }

    @OnMessage
    public void onMessage(String message, Session session) {
        log.info("userId:" +userId+">>>receive:" + message);
        try {
            // 这里可以处理消息路由逻辑
            String[] split = message.split(":", 2);

            JSONObject json = JSON.parseObject(split[1]);
            if ("group".equals(split[0])) {
                String send = String.valueOf(json.get("send"));
                switch (send) {
                    case "mac":
                        String toUserId = json.getString("mac");
                        Body body = sessionMap.get(toUserId);
                        if (null != body) {
                            body.setToUserId(userId);
                            sessionMap.get(userId).setToUserId(toUserId);
                            sendToUser(userId, "group:{'send':'msg','msg':'绑定成功！','code':'0'}");
                            sendToUser(toUserId, "group:{'send':'msg','msg':'绑定成功！','code':'0'}");
                        } else {
                            sendToUser(userId, "group:{'send':'msg','msg':'绑定失败，请先启动控制台应用，连接服务器！','code':'-1'}");
                        }
                        break;
                    case "calibrated":
                    case "no_calibrated":
                    case "yes_calibrated":
                    case "sum":
                    case "pix":
                    case "msg":
                    case "s":
                    case "q":
                    case "r":
                        sendToUser(sessionMap.get(userId).getToUserId(), message);
                        break;
                    case "add":
                        BianSaccadeTrials saccadeTrials = JSONObject.parseObject(String.valueOf(json.get("value")), BianSaccadeTrials.class);
                        saccadeTrialsMapper.addBianSaccadeTrials(saccadeTrials);
                        sendToUser(userId, "group:{'send':'msg','msg':'保存成功！','code':'0'}");
                        break;
                    default:
                        sendToUser(userId, "group:{'send':'msg','msg':'指令错误！','code':'-1'}");
                }
            } else if ("private".equals(split[0])) {
                sendToUser(sessionMap.get(userId).getToUserId(), message);
            }
        } catch (Exception e) {
            log.error("userId:" +userId+">>>Exception:" + e);
            sendToUser(userId, "group:{'send':'msg','msg':'指令错误！','code':'-1'}");
        }


    }

    @OnError
    public void onError(Session session, Throwable error) {
        log.error("userId:" +userId+">>>error:"+error);
        error.printStackTrace();
    }

    // 群发消息
    public static void sendToAll(String message, Session session) {
        log.info("group>>>send:" + message);
        for (WebSocketServer item : webSocketSet) {
            try {
                if (!item.session.equals(session)) {
                    item.session.getBasicRemote().sendText(message);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    // 私发消息
    public static void sendToUser(String userId, String message) {
        log.info("userId:" +userId+">>>send:" + message);
        Session session = sessionMap.get(userId).getSession();
        if (session != null) {
            try {
                session.getBasicRemote().sendText(message);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    public static synchronized void addOnlineCount() {
        WebSocketServer.onlineCount++;
    }

    public static synchronized void subOnlineCount() {
        WebSocketServer.onlineCount--;
    }
}